Write a custom CUDA kernel to optimize `Asymmetric Loss` (ASL).

Formula:
L = -y * (1-p)^gamma_pos * log(p) - (1-y) * (p_m)^gamma_neg * log(1-p_m)
Where p = sigmoid(logits), p_m = max(p - margin, 0).

Problem Analysis:
1. Memory Intensity: The standard implementation involves a chain of element-wise operations: sigmoid, subtraction, clamp, power, log, and conditional selection based on targets. This generates multiple intermediate tensors.
2. Branching Overhead: Processing positive and negative samples requires different formulas, often implemented via masking `y * L_pos + (1-y) * L_neg`, which computes both branches or uses expensive `torch.where`.

Optimization Strategy: Fused Element-wise Kernel with Vectorization

1. One-Thread-per-Element: Launch a grid to handle the flattened tensor.

2. Vectorized Loads (float4): Use `float4` to load logits and targets (128-bit access), maximizing memory throughput.

3. Fused Logic with Mathematical Simplification:
   - Compute `p = sigmoid(x)`.
   - Branch based on `target` (0 or 1) inside the register to avoid calculating the irrelevant branch.
   - For negatives: Compute `p_m = p - margin`. If `p_m <= 0`, loss is 0 (Hard Thresholding). Otherwise compute `pow(p_m, gamma_neg) * -log(1 - p_m)`.
   - For positives: Compute `pow(1-p, gamma_pos) * -log(p)`.

4. Reduction Handling: The kernel outputs element-wise loss. Final reduction is handled by C++ ATen primitives.
  
Here's an example to show you the syntax of inline embedding custom CUDA operators in torch: The example given architecture is:   
  
```python
import torch
import torch.nn as nn
import torch.nn.functional as F

# 多标签分类场景
BATCH_SIZE = 4096
NUM_CLASSES = 80 # COCO classes
SHAPE = (BATCH_SIZE, NUM_CLASSES)

GAMMA_POS = 0.0
GAMMA_NEG = 4.0
MARGIN = 0.05
EPS = 1e-8
REDUCTION = 'none'

class AsymmetricLoss(nn.Module):
    def __init__(self, gamma_neg=4.0, gamma_pos=1.0, clip=0.05, eps=1e-8, reduction='mean'):
        super(AsymmetricLoss, self).__init__()
        self.gamma_neg = gamma_neg
        self.gamma_pos = gamma_pos
        self.clip = clip
        self.eps = eps
        self.reduction = reduction

    def forward(self, logits: torch.Tensor, targets: torch.Tensor) -> torch.Tensor:
        # logits: (N, C)
        # targets: (N, C) binary 0/1
        p = torch.sigmoid(logits)
        
        pos_loss = (1 - p).pow(self.gamma_pos) * torch.log(p + self.eps)
        pos_loss = -pos_loss
        
        p_m = (p - self.clip).clamp(min=0.0)
        neg_loss = p_m.pow(self.gamma_neg) * torch.log(1 - p_m + self.eps)
        neg_loss = -neg_loss
        
        loss = targets * pos_loss + (1 - targets) * neg_loss
        
        if self.reduction == 'mean':
            return loss.mean()
        elif self.reduction == 'sum':
            return loss.sum()
        return loss

class Model(nn.Module):
    def __init__(self, gamma_neg=4.0, gamma_pos=1.0, clip=0.05, reduction='none'):
        super(Model, self).__init__()
        self.loss_fn = AsymmetricLoss(gamma_neg=gamma_neg, gamma_pos=gamma_pos, clip=clip, reduction=reduction)
    
    def forward(self, logits, targets):
        return self.loss_fn(logits, targets)

def get_inputs():
    logits = torch.randn(SHAPE, dtype=torch.float32)
    targets = torch.randint(0, 2, SHAPE, dtype=torch.float32)
    return [logits.contiguous(), targets.contiguous()]

def get_init_inputs():
    return [GAMMA_NEG, GAMMA_POS, MARGIN, REDUCTION]